package net.discard.util;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CookieStore;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.DnsResolver;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.FormBodyPart;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.*;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.conn.SystemDefaultDnsResolver;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.impl.cookie.BasicClientCookie2;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.util.CollectionUtils;
import sun.misc.BASE64Encoder;

import javax.net.ssl.*;
import java.io.*;
import java.net.InetAddress;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by chenyan on 16/7/7.
 */
public class HTTPClient {
    private static final Logger logger = LoggerFactory.getLogger(HTTPClient.class);

    private static final int DEFAULT_SOCKET_TIMEOUT = 11 * 1000;
    private static final Header[] DEFAULT_HEADERS = null;
    private static final HTTPProtocolThings DEFAULT_HTTP_PROTOCOL_THINGS = null;
    private static final int CONNECT_TIMEOUT = 3000;

    private static final String DEFAULT_CHARSET = "UTF-8";

    public static JsonObject makeMap2Json(Map<String, String> map) {
        JsonObject jsonObject = new JsonObject();
        if (!CollectionUtils.isEmpty(map)) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                jsonObject.addProperty(entry.getKey(), entry.getValue());
            }
        }
        return jsonObject;
    }

    public static String postJson(String url, String jsonStringContent) {
        return postJson(url, jsonStringContent, DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS);
    }

    public static String postJson(String url, Map<String, String> map) {
        JsonObject jsonObject = makeMap2Json(map);
        return postJson(url, jsonObject.toString());
    }

    public static String postJsonWithCookie(String url, String jsonStringContent, CookieStore cookieStore) {
        return postJsonWithCookie(url, jsonStringContent, DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS, cookieStore);
    }

    public static String postJsonWithCookie(String url, Map<String, String> map, CookieStore cookieStore) {
        JsonObject jsonObject = makeMap2Json(map);
        return postJsonWithCookie(url, jsonObject.toString(), DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS, cookieStore);
    }

    public static String postJson(String url, String jsonStringContent, int socketTimeout) {
        return postJson(url, jsonStringContent, DEFAULT_HEADERS, socketTimeout, DEFAULT_HTTP_PROTOCOL_THINGS);
    }

    public static String postJson(String url, Map<String, String> map, int socketTimeout) {
        JsonObject jsonObject = makeMap2Json(map);
        return postJson(url, jsonObject.toString(), DEFAULT_HEADERS, socketTimeout, DEFAULT_HTTP_PROTOCOL_THINGS);
    }

    public static String postJson(String url, String jsonStringContent, Header[] headers) {
        return postJson(url, jsonStringContent, headers, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS);
    }

    public static String postJson(String url, Map<String, String> map, Header[] headers) {
        JsonObject jsonObject = makeMap2Json(map);
        return postJson(url, jsonObject.toString(), headers, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS);
    }

    public static String postJsonWithCookie(String url, String jsonStringContent, Header[] headers, CookieStore cookieStore) {
        return postJsonWithCookie(url, jsonStringContent, headers, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS, cookieStore);
    }

    public static String postJsonWithCookie(String url, Map<String, String> map, Header[] headers, CookieStore cookieStore) {
        JsonObject jsonObject = makeMap2Json(map);
        return postJsonWithCookie(url, jsonObject.toString(), headers, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS, cookieStore);
    }

    public static String postJson(String url, String jsonStringContent, HTTPProtocolThings protocolThings) {
        return postJson(url, jsonStringContent, DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, protocolThings);
    }

    public static String postJson(String url, Map<String, String> map, HTTPProtocolThings protocolThings) {
        JsonObject jsonObject = makeMap2Json(map);
        return postJson(url, jsonObject.toString(), DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, protocolThings);
    }

    public static String postJsonWithCookie(String url, String jsonStringContent, HTTPProtocolThings protocolThings, CookieStore cookieStore) {
        return postJsonWithCookie(url, jsonStringContent, DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, protocolThings, cookieStore);
    }

    public static String postJsonWithCookie(String url, Map<String, String> map, HTTPProtocolThings protocolThings, CookieStore cookieStore) {
        JsonObject jsonObject = makeMap2Json(map);
        return postJsonWithCookie(url, jsonObject.toString(), DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, protocolThings, cookieStore);
    }

    public static String postJson(String url, String jsonStringContent, Header[] headers, int socketTimeout, HTTPProtocolThings protocolThings) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        if (protocolThings == null) {
            protocolThings = new HTTPProtocolThings();
        }
        String result = null;
        Header[] responseHeaders = null;

        HttpPost post = new HttpPost(url);
        post.setHeaders(headers);
        post.setHeader("traceId",
                MDC.get("traceId") == null ? UUID.randomUUID().toString().replace("-", "") : MDC.get("traceId"));
        post.setConfig(RequestConfig.custom()
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setSocketTimeout(socketTimeout <= 20 ? DEFAULT_SOCKET_TIMEOUT : socketTimeout)
                .build()
        );
        post.setEntity(new StringEntity(jsonStringContent, ContentType.create("application/json", DEFAULT_CHARSET)));
        HttpEntity entity = null;
        try {
            CloseableHttpResponse response = HttpClientBuilder.create().build().execute(post);
            entity = response.getEntity();
            responseHeaders = response.getAllHeaders();
            protocolThings.setStatusCode(response.getStatusLine().getStatusCode());
            protocolThings.setResponseHeaders(responseHeaders);

            if (entity != null) {
                result = EntityUtils.toString(entity, DEFAULT_CHARSET);
            }
            if (protocolThings.getStatusCode() != 200
                    && protocolThings.getStatusCode() != 201) {
                logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}, statusCode: {}",
                        "open_common_http_call_fail", url, jsonStringContent, post.getAllHeaders(), protocolThings.getStatusCode());
            }
        } catch (Exception e) {
            logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}",
                    "open_common_http_call_fail", url, jsonStringContent, post.getAllHeaders(), e);
        } finally {
            try {
                EntityUtils.consumeQuietly(entity);
                logger.info("WeLogId[{}], http 远程调用, 耗时: {}ms, url: {}, params: {}, requestHeader: {}, responseHeader: {}, result: {}",
                        "open.frame.httpClient", stopWatch.getTime(), url,
                        jsonStringContent, post.getAllHeaders(), responseHeaders, GsonUtils.forLog(result));
            } catch (Exception e) {
                logger.error("HttpClient finally Error", e);
            }

        }
        return result;
    }

    public static String postJsonWithCookie(String url, String jsonStringContent, Header[] headers, int socketTimeout, HTTPProtocolThings protocolThings, CookieStore cookieStore) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        if (protocolThings == null) {
            protocolThings = new HTTPProtocolThings();
        }
        String result = null;
        Header[] responseHeaders = null;

        HttpPost post = new HttpPost(url);
        post.setHeaders(headers);
        post.setHeader("traceId",
                MDC.get("traceId") == null ? UUID.randomUUID().toString().replace("-", "") : MDC.get("traceId"));
        post.setConfig(RequestConfig.custom()
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setSocketTimeout(socketTimeout <= 20 ? DEFAULT_SOCKET_TIMEOUT : socketTimeout)
                .build()
        );
        post.setEntity(new StringEntity(jsonStringContent, ContentType.create("application/json", DEFAULT_CHARSET)));
        HttpEntity entity = null;
        try {
            if (cookieStore == null || cookieStore.getCookies() == null) {
                cookieStore = new BasicCookieStore();
            }
            CloseableHttpResponse response = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build().execute(post);
            entity = response.getEntity();
            responseHeaders = response.getAllHeaders();
            protocolThings.setStatusCode(response.getStatusLine().getStatusCode());
            protocolThings.setResponseHeaders(responseHeaders);

            if (entity != null) {
                result = EntityUtils.toString(entity, DEFAULT_CHARSET);
            }
            if (protocolThings.getStatusCode() != 200
                    && protocolThings.getStatusCode() != 201) {
                logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}, statusCode: {}",
                        "open_common_http_call_fail", url, jsonStringContent, post.getAllHeaders(), protocolThings.getStatusCode());
            }
        } catch (Exception e) {
            logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}",
                    "open_common_http_call_fail", url, jsonStringContent, post.getAllHeaders(), e);
        } finally {
            try {
                EntityUtils.consumeQuietly(entity);
                logger.info("WeLogId[{}], http 远程调用, 耗时: {}ms, url: {}, params: {}, requestHeader: {}, responseHeader: {}, result: {}",
                        "open.frame.httpClient", stopWatch.getTime(), url,
                        jsonStringContent, post.getAllHeaders(), responseHeaders, GsonUtils.forLog(result));

            } catch (Exception e) {
                logger.error("HttpClient finally Error", e);
            }
        }
        return result;
    }

    public static String postMap(String url, Map<String, String> paramsMap) {
        return postMap(url, paramsMap, DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS);
    }

    public static String postMapWithCookie(String url, Map<String, String> paramsMap, CookieStore cookieStore) {
        return postMapWithCookie(url, paramsMap, DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS, cookieStore);
    }

    public static String postMap(String url, Map<String, String> paramsMap, Header[] headers) {
        return postMap(url, paramsMap, headers, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS);
    }

    public static String postMapWithCookie(String url, Map<String, String> paramsMap, Header[]
            headers, CookieStore cookieStore) {
        return postMapWithCookie(url, paramsMap, headers, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS, cookieStore);
    }

    public static String postMap(String url, Map<String, String> paramsMap, Header[] headers, int timeout) {
        return postMap(url, paramsMap, headers, timeout, DEFAULT_HTTP_PROTOCOL_THINGS);
    }

    public static String postMapWithCookie(String url, Map<String, String> paramsMap, Header[] headers,
                                           int timeout, CookieStore cookieStore) {
        return postMapWithCookie(url, paramsMap, headers, timeout, DEFAULT_HTTP_PROTOCOL_THINGS, cookieStore);
    }

    public static String postMap(String url, Map<String, String> paramsMap, HTTPProtocolThings protocolThings) {
        return postMap(url, paramsMap, DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, protocolThings);
    }

    public static String postMapWithCookie(String url, Map<String, String> paramsMap, HTTPProtocolThings
            protocolThings, CookieStore cookieStore) {
        return postMapWithCookie(url, paramsMap, DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, protocolThings, cookieStore);
    }

    public static String postMap(String url, Map<String, String> paramsMap, Header[] headers,
                                 int socketTimeout, HTTPProtocolThings protocolThings) {
        List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();
        if (paramsMap != null) {
            for (String key : paramsMap.keySet()) {
                nameValuePairList.add(new BasicNameValuePair(key, paramsMap.get(key)));
            }
        }
        return postEncodedForm(url, nameValuePairList, headers, socketTimeout, protocolThings);
    }

    public static String postMapWithCookie(String url, Map<String, String> paramsMap, Header[] headers,
                                           int socketTimeout, HTTPProtocolThings protocolThings, CookieStore cookieStore) {
        List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();
        if (paramsMap != null) {
            for (String key : paramsMap.keySet()) {
                nameValuePairList.add(new BasicNameValuePair(key, paramsMap.get(key)));
            }
        }
        return postEncodedFormWithCookie(url, nameValuePairList, headers, socketTimeout, protocolThings, cookieStore);
    }


    private static String postEncodedForm(String url, List<NameValuePair> nameValuePairList, Header[] headers,
                                          int socketTimeout, HTTPProtocolThings protocolThings) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        if (protocolThings == null) {
            protocolThings = new HTTPProtocolThings();
        }
        String result = null;
        Header[] responseHeaders = null;

        HttpPost post = new HttpPost(url);
        post.setHeaders(headers);
        post.setHeader("traceId",
                MDC.get("traceId") == null ? UUID.randomUUID().toString().replace("-", "") : MDC.get("traceId"));
        post.setConfig(RequestConfig.custom()
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setSocketTimeout(socketTimeout <= 0 ? DEFAULT_SOCKET_TIMEOUT : socketTimeout)
                .build()
        );
        HttpEntity entity = null;
        try {
            post.setEntity(new UrlEncodedFormEntity(nameValuePairList, DEFAULT_CHARSET));
            CloseableHttpResponse response = HttpClientBuilder.create().build().execute(post);
            entity = response.getEntity();
            responseHeaders = response.getAllHeaders();
            protocolThings.setStatusCode(response.getStatusLine().getStatusCode());
            protocolThings.setResponseHeaders(responseHeaders);

            if (entity != null) {
                result = EntityUtils.toString(entity, DEFAULT_CHARSET);
            }
            if (protocolThings.getStatusCode() != 200
                    && protocolThings.getStatusCode() != 201) {
                logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}, statusCode: {}",
                        "open_common_http_call_fail", url, nameValuePairList, post.getAllHeaders(), protocolThings.getStatusCode());
            }
        } catch (Exception e) {
            logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}",
                    "open_common_http_call_fail", url, nameValuePairList, post.getAllHeaders(), e);
        } finally {
            try {
                EntityUtils.consumeQuietly(entity);
                logger.info("WeLogId[{}], http 远程调用, 耗时: {}ms, url: {}, params: {}, requestHeader: {}, responseHeader: {}, result: {}",
                        "open.frame.httpClient", stopWatch.getTime(), url,
                        nameValuePairList, post.getAllHeaders(), responseHeaders, GsonUtils.forLog(result));
            } catch (Exception e) {
                logger.error("HttpClient finally Error", e);
            }

        }
        return result;
    }

    private static String postEncodedFormWithCookie(String url, List<NameValuePair> nameValuePairList, Header[]
            headers, int socketTimeout, HTTPProtocolThings protocolThings, CookieStore cookieStore) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        if (protocolThings == null) {
            protocolThings = new HTTPProtocolThings();
        }
        String result = null;
        Header[] responseHeaders = null;

        HttpPost post = new HttpPost(url);
        post.setHeaders(headers);
        post.setHeader("traceId",
                MDC.get("traceId") == null ? UUID.randomUUID().toString().replace("-", "") : MDC.get("traceId"));
        post.setConfig(RequestConfig.custom()
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setSocketTimeout(socketTimeout <= 0 ? DEFAULT_SOCKET_TIMEOUT : socketTimeout)
                .build()
        );
        HttpEntity entity = null;
        try {
            post.setEntity(new UrlEncodedFormEntity(nameValuePairList, DEFAULT_CHARSET));
            if (cookieStore == null || cookieStore.getCookies() == null) {
                cookieStore = new BasicCookieStore();
            }
            CloseableHttpResponse response = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build().execute(post);
            entity = response.getEntity();
            responseHeaders = response.getAllHeaders();
            protocolThings.setStatusCode(response.getStatusLine().getStatusCode());
            protocolThings.setResponseHeaders(responseHeaders);

            if (entity != null) {
                result = EntityUtils.toString(entity, DEFAULT_CHARSET);
            }
            if (protocolThings.getStatusCode() != 200
                    && protocolThings.getStatusCode() != 201) {
                logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}, statusCode: {}",
                        "open_common_http_call_fail", url, nameValuePairList, post.getAllHeaders(), protocolThings.getStatusCode());
            }
        } catch (Exception e) {
            logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}",
                    "open_common_http_call_fail", url, nameValuePairList, post.getAllHeaders(), e);
        } finally {
            try {
                EntityUtils.consumeQuietly(entity);
                logger.info("WeLogId[{}], http 远程调用, 耗时: {}ms, url: {}, params: {}, requestHeader: {}, responseHeader: {}, result: {}",
                        "open.frame.httpClient", stopWatch.getTime(), url,
                        nameValuePairList, post.getAllHeaders(), responseHeaders, GsonUtils.forLog(result));
            } catch (Exception e) {
                logger.error("HttpClient finally Error", e);
            }

        }
        return result;
    }

    /**
     * FormBodyPartBuilder.create("参数名",
     * new InputStreamBody(multipartFile.getInputStream(),
     * ContentType.create(multipartFile.getContentType(), "utf8"),
     * multipartFile.getOriginalFilename()
     * )
     * ).build()
     *
     * @param url
     * @param formBodyPartList
     * @param paramsMap        不能为null
     * @param headers
     * @param socketTimeout
     * @param protocolThings
     * @return
     */
    public static String postFile(String
                                          url, List<FormBodyPart> formBodyPartList, Map<String, String> paramsMap,
                                  Header[] headers, int socketTimeout, HTTPProtocolThings protocolThings) {
        if (paramsMap == null) {
            paramsMap = new HashMap<>();
        }
        if (protocolThings == null) {
            protocolThings = new HTTPProtocolThings();
        }
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        String result = null;
        Header[] responseHeaders = null;

        HttpPost post = new HttpPost(url);
        post.setHeaders(headers);
        post.setHeader("traceId",
                MDC.get("traceId") == null ? UUID.randomUUID().toString().replace("-", "") : MDC.get("traceId"));
        post.setConfig(RequestConfig.custom()
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setSocketTimeout(socketTimeout <= 0 ? DEFAULT_SOCKET_TIMEOUT : socketTimeout)
                .build()
        );
        HttpEntity entity = null;
        try {
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            formBodyPartList.forEach(multipartEntityBuilder::addPart);
            paramsMap.forEach((k, v) -> multipartEntityBuilder.addTextBody(k, v, ContentType.create("text/plain", "utf8")));
            String boundary = "----------boundary-" + UUID.randomUUID().toString().replace("-", "");
            multipartEntityBuilder.setBoundary(boundary);
            post.setHeader("Content-Type", "multipart/form-data;boundary=" + boundary);
            post.setEntity(multipartEntityBuilder.build());
            CloseableHttpResponse response = HttpClientBuilder.create().build().execute(post);
            entity = response.getEntity();
            responseHeaders = response.getAllHeaders();
            protocolThings.setStatusCode(response.getStatusLine().getStatusCode());
            protocolThings.setResponseHeaders(responseHeaders);

            if (entity != null) {
                result = EntityUtils.toString(entity, DEFAULT_CHARSET);
            }
            if (protocolThings.getStatusCode() != 200
                    && protocolThings.getStatusCode() != 201) {
                logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, paramFile: {}, header: {}, statusCode: {}",
                        "open_common_http_call_fail", url, paramsMap, GsonUtils.forLog(formBodyPartList), post.getAllHeaders(), protocolThings.getStatusCode());
            }
        } catch (Exception e) {
            logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, paramFile: {}, header: {}",
                    "open_common_http_call_fail", url, paramsMap, GsonUtils.forLog(formBodyPartList), post.getAllHeaders(), e);
        } finally {
            try {
                EntityUtils.consumeQuietly(entity);
                logger.info("WeLogId[{}], http 远程调用, 耗时: {}ms, url: {}, params: {}, paramFile: {}, requestHeader: {}, responseHeader: {}, result: {}",
                        "open.frame.httpClient", stopWatch.getTime(), url, paramsMap, GsonUtils.forLog(formBodyPartList), post.getAllHeaders(), responseHeaders, GsonUtils.forLog(result));
            } catch (Exception e) {
                logger.error("HttpClient finally Error", e);
            }

        }
        return result;
    }

    public static String get(String url) {
        return get(url, "", DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS);
    }

    public static String getWithCookie(String url, CookieStore cookieStore) {
        return getWithCookie(url, "", DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS, cookieStore);
    }

    public static String get(String url, String param) {
        return get(url, param, DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS);
    }

    public static String getWithCookie(String url, String param, CookieStore cookieStore) {
        return getWithCookie(url, param, DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS, cookieStore);
    }

    public static String get(String url, String param, Header[] headers) {
        return get(url, param, headers, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS);
    }

    public static String getWithCookie(String url, String param, Header[] headers, CookieStore cookieStore) {
        return getWithCookie(url, param, headers, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS, cookieStore);
    }

    public static String get(String url, String param, HTTPProtocolThings protocolThings) {
        return get(url, param, DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, protocolThings);
    }

    public static String getWithCookie(String url, String param, HTTPProtocolThings protocolThings, CookieStore
            cookieStore) {
        return getWithCookie(url, param, DEFAULT_HEADERS, DEFAULT_SOCKET_TIMEOUT, protocolThings, cookieStore);
    }

    public static String get(String url, String param, Header[] headers, int socketTimeout, HTTPProtocolThings
            protocolThings) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        if (protocolThings == null) {
            protocolThings = new HTTPProtocolThings();
        }
        String result = null;
        Header[] responseHeaders = null;
        HttpEntity entity = null;
        if (StringUtils.isNotEmpty(param) && param.contains("=")) {
            url = url.contains("?") ? url + "&" + param : url + "?" + param;
        }
        HttpGet get = null;
        try {
            get = new HttpGet(url);
            get.setHeaders(headers);
            get.setHeader("traceId",
                    MDC.get("traceId") == null ? UUID.randomUUID().toString().replace("-", "") : MDC.get("traceId"));
            get.setConfig(RequestConfig.custom()
                    .setConnectTimeout(CONNECT_TIMEOUT)
                    .setSocketTimeout(socketTimeout <= 50 ? DEFAULT_SOCKET_TIMEOUT : socketTimeout)
                    .build());

            CloseableHttpResponse response = HttpClientBuilder.create().build().execute(get);
            entity = response.getEntity();
            responseHeaders = response.getAllHeaders();
            protocolThings.setStatusCode(response.getStatusLine().getStatusCode());
            protocolThings.setResponseHeaders(responseHeaders);

            if (entity != null) {
                result = EntityUtils.toString(entity, DEFAULT_CHARSET);
            }
            if (protocolThings.getStatusCode() != 200
                    && protocolThings.getStatusCode() != 201) {
                logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}, statusCode: {}",
                        "open_common_http_call_fail", url, param, get.getAllHeaders(), protocolThings.getStatusCode());
            }
        } catch (Exception e) {
            logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}",
                    "open_common_http_call_fail", url, param, get.getAllHeaders(), e);
        } finally {
            try {
                EntityUtils.consumeQuietly(entity);
                logger.info("WeLogId[{}], http 远程调用, 耗时: {}ms, url: {}, params: {}, requestHeader: {}, responseHeader: {}, result: {}",
                        "open.frame.httpClient", stopWatch.getTime(), url,
                        param, get.getAllHeaders(), responseHeaders, GsonUtils.forLog(result));
            } catch (Exception e) {
                logger.error("HttpClient finally Error", e);
            }

        }
        return result;
    }

    public static byte[] getImage(String url, Header[] headers, CookieStore cookieStore) {
        return getImage(url, null, headers, DEFAULT_SOCKET_TIMEOUT, DEFAULT_HTTP_PROTOCOL_THINGS, cookieStore);
    }

    public static byte[] getImage(String url, String param, Header[] headers, int socketTimeout, HTTPProtocolThings
            protocolThings, CookieStore cookieStore) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        if (protocolThings == null) {
            protocolThings = new HTTPProtocolThings();
        }
        String result = null;
        Header[] responseHeaders = null;
        HttpEntity entity = null;
        if (StringUtils.isNotEmpty(param) && param.contains("=")) {
            url = url.contains("?") ? url + "&" + param : url + "?" + param;
        }
        HttpGet get = null;
        byte[] bytes = null;
        try {
            get = new HttpGet(url);
            get.setHeaders(headers);
            get.setHeader("traceId",
                    MDC.get("traceId") == null ? UUID.randomUUID().toString().replace("-", "") : MDC.get("traceId"));
            get.setConfig(RequestConfig.custom()
                    .setConnectTimeout(CONNECT_TIMEOUT)
                    .setSocketTimeout(socketTimeout <= 50 ? DEFAULT_SOCKET_TIMEOUT : socketTimeout)
                    .build());
            if (cookieStore == null || cookieStore.getCookies() == null) {
                cookieStore = new BasicCookieStore();
            }
            get.setHeader("content-type", "image/jpeg");
            CloseableHttpResponse response = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build().execute(get);
            entity = response.getEntity();
            responseHeaders = response.getAllHeaders();
            protocolThings.setStatusCode(response.getStatusLine().getStatusCode());
            protocolThings.setResponseHeaders(responseHeaders);

            if (entity != null) {
                //todo 此处建议换做 bytes = EntityUtils.toByteArray(entity);
                InputStream inputStream = entity.getContent();
                byte[] buff = new byte[1024];
                ByteArrayOutputStream output = new ByteArrayOutputStream();
                int count = -1;
                while ((count = inputStream.read(buff, 0, 1024)) != -1) {
                    output.write(buff, 0, count);
                }
                bytes = output.toByteArray();
                inputStream.close();
                output.close();
            }
            if (protocolThings.getStatusCode() != 200
                    && protocolThings.getStatusCode() != 201) {
                logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}, statusCode: {}",
                        "open_common_http_call_fail", url, param, get.getAllHeaders(), protocolThings.getStatusCode());
            }
        } catch (Exception e) {
            logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}",
                    "open_common_http_call_fail", url, param, get.getAllHeaders(), e);
        } finally {
            try {
                EntityUtils.consumeQuietly(entity);
                logger.info("WeLogId[{}], http 远程调用, 耗时: {}ms, url: {}, params: {}, requestHeader: {}, responseHeader: {}, result: {}",
                        "open.frame.httpClient", stopWatch.getTime(), url,
                        param, get.getAllHeaders(), responseHeaders, GsonUtils.forLog(result));
            } catch (Exception e) {
                logger.error("HttpClient finally Error", e);
            }

        }
        return bytes;
    }

    public static String getWithCookie(String url, String param, Header[] headers,
                                       int socketTimeout, HTTPProtocolThings protocolThings, CookieStore cookieStore) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        if (protocolThings == null) {
            protocolThings = new HTTPProtocolThings();
        }
        String result = null;
        Header[] responseHeaders = null;
        HttpEntity entity = null;
        if (StringUtils.isNotEmpty(param) && param.contains("=")) {
            url = url.contains("?") ? url + "&" + param : url + "?" + param;
        }
        HttpGet get = null;
        try {
            get = new HttpGet(url);
            get.setHeaders(headers);
            get.setHeader("traceId",
                    MDC.get("traceId") == null ? UUID.randomUUID().toString().replace("-", "") : MDC.get("traceId"));
            get.setConfig(RequestConfig.custom()
                    .setConnectTimeout(CONNECT_TIMEOUT)
                    .setSocketTimeout(socketTimeout <= 50 ? DEFAULT_SOCKET_TIMEOUT : socketTimeout)
                    .build());

            if (cookieStore == null || cookieStore.getCookies() == null) {
                cookieStore = new BasicCookieStore();
            }
            CloseableHttpClient client = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build();
            CloseableHttpResponse response = client.execute(get);
            entity = response.getEntity();
            responseHeaders = response.getAllHeaders();
            protocolThings.setStatusCode(response.getStatusLine().getStatusCode());
            protocolThings.setResponseHeaders(responseHeaders);
            if (entity != null) {
                result = EntityUtils.toString(entity, DEFAULT_CHARSET);
            }
            if (protocolThings.getStatusCode() != 200
                    && protocolThings.getStatusCode() != 201) {
                logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}, statusCode: {}",
                        "open_common_http_call_fail", url, param, get.getAllHeaders(), protocolThings.getStatusCode());
            }
        } catch (Exception e) {
            logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}",
                    "open_common_http_call_fail", url, param, get.getAllHeaders(), e);
        } finally {
            try {
                EntityUtils.consumeQuietly(entity);
                logger.info("WeLogId[{}], http 远程调用, 耗时: {}ms, url: {}, params: {}, requestHeader: {}, responseHeader: {}, result: {}",
                        "open.frame.httpClient", stopWatch.getTime(), url,
                        param, get.getAllHeaders(), responseHeaders, GsonUtils.forLog(result));
            } catch (Exception e) {
                logger.error("HttpClient finally Error", e);
            }

        }
        return result;
    }

    public static String post(HTTPBuilder builder) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        HTTPProtocolThings protocolThings = new HTTPProtocolThings();
        String result = null;
        Header[] responseHeaders = null;

        // url优先取eureka的
        String url = builder.getUrl();

        HttpPost post = new HttpPost(url);

        Header[] headers = builder.getHeaders();
        Header[] newHeaders = null;
        if (builder.isNeedXForward() || !StringUtils.isEmpty(builder.getxForwardIp())) {
            if (headers == null) {
                newHeaders = new Header[1];
            } else {
                newHeaders = new Header[headers.length + 1];
                for (int i = 0; i < headers.length; i++) {
                    newHeaders[i] = headers[i];
                }
            }
            String xIp = builder.getxForwardIp();
            if (StringUtils.isEmpty(xIp)) {
                xIp = getRndIP();
            }
            newHeaders[newHeaders.length - 1] = new BasicHeader("X-Forwarded-For", xIp);
        }
        if (newHeaders != null) {
            post.setHeaders(newHeaders);
        } else if (headers != null) {
            post.setHeaders(newHeaders);
        }

        // NameValuePairList
        try {
            if (!CollectionUtils.isEmpty(builder.getNameValuePairList())) {
                post.setEntity(new UrlEncodedFormEntity(builder.getNameValuePairList(), DEFAULT_CHARSET));
            }
        } catch (Exception e) {
            logger.error("设置nameValuePaire异常。", e);
        }


        post.setHeader("traceId",
                MDC.get("traceId") == null ? UUID.randomUUID().toString().replace("-", "") : MDC.get("traceId"));

        int connectTimeout = builder.getConnectTimeout() > 0 ? builder.getConnectTimeout() : CONNECT_TIMEOUT;
        int socketTimeout = builder.getSocketTimeout() > 0 ? builder.getSocketTimeout() : DEFAULT_SOCKET_TIMEOUT;
        post.setConfig(RequestConfig.custom()
                .setConnectTimeout(connectTimeout)
                .setSocketTimeout(socketTimeout)
                .build()
        );

        if (!StringUtils.isEmpty(builder.getParam())) {
            post.setEntity(new StringEntity(builder.getParam(), ContentType.create("application/json", DEFAULT_CHARSET)));
        }

        HttpEntity entity = null;
        try {
            HttpClientBuilder build = HttpClients.custom();
            // 设置cookieStore
            CookieStore cookieStore = builder.getCookieStore() == null ? new BasicCookieStore() : builder.getCookieStore();
            build.setDefaultCookieStore(cookieStore);

            // 设置CDN
            if (!StringUtils.isEmpty(builder.getCdn())) {
                DnsResolver dnsResolver = new SystemDefaultDnsResolver() {
                    @Override
                    public InetAddress[] resolve(final String host) throws UnknownHostException {
                        return new InetAddress[]{InetAddress.getByName(builder.getCdn())};
                    }
                };

                BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(
                        RegistryBuilder.<ConnectionSocketFactory>create()
                                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                                .build(),
                        null,
                        null,
                        dnsResolver
                );
                build.setConnectionManager(connManager);
            }
            // 判断是否需要ssl证书
            if (builder.getNeedSSL()) {
                setSSL(build);
            }
            CloseableHttpClient client = build.build();

            CloseableHttpResponse response = client.execute(post);
            entity = response.getEntity();
            responseHeaders = response.getAllHeaders();
            protocolThings.setStatusCode(response.getStatusLine().getStatusCode());
            protocolThings.setResponseHeaders(responseHeaders);

            if (entity != null) {
                result = EntityUtils.toString(entity, DEFAULT_CHARSET);
            }
            if (protocolThings.getStatusCode() != 200
                    && protocolThings.getStatusCode() != 201 && builder.getLog()) {
                logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}, statusCode: {}",
                        "open_common_http_call_fail", url, builder.getParam(), post.getAllHeaders(), protocolThings.getStatusCode());
            }
        } catch (Exception e) {
            logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}",
                    "open_common_http_call_fail", url, builder.getParam(), post.getAllHeaders(), e);
        } finally {
            try {
                EntityUtils.consumeQuietly(entity);
                if (builder.getLog()) {
                    logger.info("WeLogId[{}], http 远程调用, 耗时: {}ms, url: {}, params: {}, requestHeader: {}, responseHeader: {}, result: {}",
                            "open.frame.httpClient", stopWatch.getTime(), url,
                            builder.getParam(), post.getAllHeaders(), responseHeaders, GsonUtils.forLog(result));
                }
                MDC.put("costTime", stopWatch.getTime() + "");
            } catch (Exception e) {
                logger.error("HttpClient finally Error", e);
            }

        }
        return result;
    }

    public static String get(HTTPBuilder builder) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        HTTPProtocolThings protocolThings = new HTTPProtocolThings();
        String result = null;
        Header[] responseHeaders = null;
        HttpEntity entity = null;

        String url = builder.getUrl();

        // 拼接url参数
        String param = builder.getParam();
        if (StringUtils.isNotEmpty(param) && param.contains("=")) {
            url = url.contains("?") ? url + "&" + param : url + "?" + param;
        }
        if (!CollectionUtils.isEmpty(builder.getNameValuePairList())) {
            for (NameValuePair pair : builder.getNameValuePairList()) {
                String value = pair.getName() + "=" + pair.getValue();
                url = url.contains("?") ? url + "&" + value : url + "?" + value;
            }
        }
        HttpGet get = null;
        try {
            HttpClientBuilder build = HttpClients.custom();
            // 设置cookieStore
            CookieStore cookieStore = builder.getCookieStore() == null ? new BasicCookieStore() : builder.getCookieStore();
            build.setDefaultCookieStore(cookieStore);

            // 设置CDN
            if (!StringUtils.isEmpty(builder.getCdn())) {
                DnsResolver dnsResolver = new SystemDefaultDnsResolver() {
                    @Override
                    public InetAddress[] resolve(final String host) throws UnknownHostException {
                        return new InetAddress[]{InetAddress.getByName(builder.getCdn())};
                    }
                };

                BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(
                        RegistryBuilder.<ConnectionSocketFactory>create()
                                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                                .build(),
                        null,
                        null,
                        dnsResolver
                );
                build.setConnectionManager(connManager);
            }
            // 判断是否需要ssl证书
            if (builder.getNeedSSL()) {
                setSSL(build);
            }
            CloseableHttpClient client = build.build();

            get = new HttpGet(url);
            Header[] headers = builder.getHeaders();
            Header[] newHeaders = null;
            if (builder.isNeedXForward() || !StringUtils.isEmpty(builder.getxForwardIp())) {
                if (headers == null) {
                    newHeaders = new Header[1];
                } else {
                    newHeaders = new Header[headers.length + 1];
                    for (int i = 0; i < headers.length; i++) {
                        newHeaders[i] = headers[i];
                    }
                }
                String xIp = builder.getxForwardIp();
                if (StringUtils.isEmpty(xIp)) {
                    xIp = getRndIP();
                }
                newHeaders[newHeaders.length - 1] = new BasicHeader("X-Forwarded-For", xIp);
            }
            if (newHeaders != null) {
                get.setHeaders(newHeaders);
            } else if (headers != null) {
                get.setHeaders(newHeaders);
            }


            get.setHeader("traceId",
                    MDC.get("traceId") == null ? UUID.randomUUID().toString().replace("-", "") : MDC.get("traceId"));
            int connectTimeout = builder.getConnectTimeout() > 0 ? builder.getConnectTimeout() : CONNECT_TIMEOUT;
            int socketTimeout = builder.getSocketTimeout() > 0 ? builder.getSocketTimeout() : DEFAULT_SOCKET_TIMEOUT;
            get.setConfig(RequestConfig.custom()
                    .setConnectTimeout(connectTimeout)
                    .setSocketTimeout(socketTimeout)
                    .build()
            );

            CloseableHttpResponse response = client.execute(get);
            entity = response.getEntity();
            responseHeaders = response.getAllHeaders();
            protocolThings.setStatusCode(response.getStatusLine().getStatusCode());
            protocolThings.setResponseHeaders(responseHeaders);
            if (entity != null) {
                result = EntityUtils.toString(entity, DEFAULT_CHARSET);
            }
            if (protocolThings.getStatusCode() != 200
                    && protocolThings.getStatusCode() != 201 && builder.getLog()) {
                logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}, statusCode: {}",
                        "open_common_http_call_fail", url, param, get.getAllHeaders(), protocolThings.getStatusCode());
            }
        } catch (Exception e) {
            logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}",
                    "open_common_http_call_fail", url, param, get.getAllHeaders(), e);
        } finally {
            try {
                EntityUtils.consumeQuietly(entity);
                if (builder.getLog()) {
                    logger.info("WeLogId[{}], http 远程调用, 耗时: {}ms, url: {}, params: {}, requestHeader: {}, responseHeader: {}, result: {}",
                            "open.frame.httpClient", stopWatch.getTime(), url,
                            param, get.getAllHeaders(), responseHeaders, GsonUtils.forLog(result));
                }
                MDC.put("costTime", stopWatch.getTime() + "");
            } catch (Exception e) {
                logger.error("HttpClient finally Error", e);
            }

        }
        return result;
    }

    public static byte[] getImage(HTTPBuilder builder) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        HTTPProtocolThings protocolThings = new HTTPProtocolThings();
        byte[] bytes = null;
        Header[] responseHeaders = null;
        HttpEntity entity = null;

        // url优先取eureka的
        String url = builder.getUrl();

        // 拼接url参数
        String param = builder.getParam();
        if (StringUtils.isNotEmpty(param) && param.contains("=")) {
            url = url.contains("?") ? url + "&" + param : url + "?" + param;
        }
        HttpGet get = null;
        try {
            HttpClientBuilder build = HttpClients.custom();
            // 设置cookieStore
            CookieStore cookieStore = builder.getCookieStore() == null ? new BasicCookieStore() : builder.getCookieStore();
            build.setDefaultCookieStore(cookieStore);

            // 设置CDN
            if (!StringUtils.isEmpty(builder.getCdn())) {
                DnsResolver dnsResolver = new SystemDefaultDnsResolver() {
                    @Override
                    public InetAddress[] resolve(final String host) throws UnknownHostException {
                        return new InetAddress[]{InetAddress.getByName(builder.getCdn())};
                    }
                };

                BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(
                        RegistryBuilder.<ConnectionSocketFactory>create()
                                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                                .build(),
                        null,
                        null,
                        dnsResolver
                );
                build.setConnectionManager(connManager);
            }
            // 判断是否需要ssl证书
            if (builder.getNeedSSL()) {
                setSSL(build);
            }
            CloseableHttpClient client = build.build();

            get = new HttpGet(url);
            Header[] headers = builder.getHeaders();
            Header[] newHeaders = null;
            if (builder.isNeedXForward() || !StringUtils.isEmpty(builder.getxForwardIp())) {
                if (headers == null) {
                    newHeaders = new Header[1];
                } else {
                    newHeaders = new Header[headers.length + 1];
                    for (int i = 0; i < headers.length; i++) {
                        newHeaders[i] = headers[i];
                    }
                }
                String xIp = builder.getxForwardIp();
                if (StringUtils.isEmpty(xIp)) {
                    xIp = getRndIP();
                }
                newHeaders[newHeaders.length - 1] = new BasicHeader("X-Forwarded-For", xIp);
            }
            if (newHeaders != null) {
                get.setHeaders(newHeaders);
            } else if (headers != null) {
                get.setHeaders(newHeaders);
            }
            get.setHeader("traceId",
                    MDC.get("traceId") == null ? UUID.randomUUID().toString().replace("-", "") : MDC.get("traceId"));
            int connectTimeout = builder.getConnectTimeout() > 0 ? builder.getConnectTimeout() : CONNECT_TIMEOUT;
            int socketTimeout = builder.getSocketTimeout() > 0 ? builder.getSocketTimeout() : DEFAULT_SOCKET_TIMEOUT;
            get.setConfig(RequestConfig.custom()
                    .setConnectTimeout(connectTimeout)
                    .setSocketTimeout(socketTimeout)
                    .build()
            );

            CloseableHttpResponse response = client.execute(get);
            entity = response.getEntity();
            responseHeaders = response.getAllHeaders();
            protocolThings.setStatusCode(response.getStatusLine().getStatusCode());
            protocolThings.setResponseHeaders(responseHeaders);

            if (entity != null) {
                InputStream inputStream = entity.getContent();
                byte[] buff = new byte[2048];
                ByteArrayOutputStream output = new ByteArrayOutputStream();
                int count = -1;
                while ((count = inputStream.read(buff, 0, 2048)) != -1) {
                    output.write(buff, 0, count);
                }
                bytes = output.toByteArray();
                inputStream.close();
                output.close();
            }
            if (protocolThings.getStatusCode() != 200
                    && protocolThings.getStatusCode() != 201 && builder.getLog()) {
                logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}, statusCode: {}",
                        "open_common_http_call_fail", url, param, get.getAllHeaders(), protocolThings.getStatusCode());
            }
        } catch (Exception e) {
            logger.error("WeLogId[{}], http 远程调用异常, url: {}, params: {}, header: {}",
                    "open_common_http_call_fail", url, param, get.getAllHeaders(), e);
        } finally {
            try {
                EntityUtils.consumeQuietly(entity);
                if (builder.getLog()) {
                    logger.info("WeLogId[{}], http 远程调用, 耗时: {}ms, url: {}, params: {}, requestHeader: {}, responseHeader: {}",
                            "open.frame.httpClient", stopWatch.getTime(), url,
                            param, get.getAllHeaders(), responseHeaders);
                }
                MDC.put("costTime", stopWatch.getTime() + "");
            } catch (Exception e) {
                logger.error("HttpClient finally Error", e);
            }

        }
        return bytes;
    }

    private static void setSSL(HttpClientBuilder builder) {
        try {
            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }

                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
                            // don't check
                        }

                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
                            // don't check
                        }
                    }
            };

            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, trustAllCerts, null);

            LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(ctx);
            builder.setSSLSocketFactory(sslSocketFactory);
        } catch (Exception e) {
            logger.error("SSL证书生成异常。", e);
        }

    }

    public static class MyVerifyHostname implements HostnameVerifier {

        @Override
        public boolean verify(String arg0, SSLSession arg1) {
            return true;
        }

    }

    public static void main(String[] args) {
//        String url = "http://113.107.57.43/otn/uamauthclient";
//        Header[] headers = new Header[10];
//        headers[0] = new BasicHeader("Host", "kyfw.12306.cn");
//        headers[1] = new BasicHeader("Connection", "keep-alive");
//        headers[2] = new BasicHeader("Accept", "*/*");
//        headers[3] = new BasicHeader("Origin", "https://kyfw.12306.cn");
//        headers[4] = new BasicHeader("X-Requested-With", "XMLHttpRequest");
//        headers[5] = new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36");
//        headers[6] = new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
//        headers[7] = new BasicHeader("Referer", "https://kyfw.12306.cn/otn/leftTicket/init");
//        headers[8] = new BasicHeader("Accept-Encoding", "gzip, deflate, br");
//        headers[9] = new BasicHeader("Accept-Language", "zh-CN,zh;q=0.9");
//
//        CookieStore cookieStore = new BasicCookieStore();
//        BasicClientCookie cookie1 = new BasicClientCookie("_jc_save_wfdc_flag", "dc");
//        cookie1.setDomain("kyfw.12306.cn");
//        cookie1.setPath("/");
//        cookieStore.addCookie(cookie1);
//        BasicClientCookie cookie2 = new BasicClientCookie("_jc_save_toStation", "大灰厂,DHP");
//        cookie2.setDomain("kyfw.12306.cn");
//        cookie2.setPath("/");
//        cookieStore.addCookie(cookie2);
//        BasicClientCookie cookie3 = new BasicClientCookie("_jc_save_toDate", "2017-11-29");
//        cookie3.setDomain("kyfw.12306.cn");
//        cookie3.setPath("/");
//        cookieStore.addCookie(cookie3);
//        BasicClientCookie cookie4 = new BasicClientCookie("_jc_save_toDate", "2017-11-29");
//        cookie4.setDomain("kyfw.12306.cn");
//        cookie4.setPath("/");
//        cookieStore.addCookie(cookie3);
//        cookieStore.addCookie(new BasicClientCookie("_jc_save_showIns", "true"));
//        cookieStore.addCookie(new BasicClientCookie("_jc_save_fromStation", "北京,VNP"));
//        cookieStore.addCookie(new BasicClientCookie("_jc_save_fromDate", "2017-11-29"));
//        cookieStore.addCookie(new BasicClientCookie("_jc_save_detail", "true"));
//        cookieStore.addCookie(new BasicClientCookie("_jc_save_czxxcx_toStation", "北京,BJP"));
//        cookieStore.addCookie(new BasicClientCookie("_jc_save_czxxcx_fromDate", "2017-11-03"));
//        cookieStore.addCookie(new BasicClientCookie("route", "495c805987d0f5c8c84b14f60212447d"));
//        cookieStore.addCookie(new BasicClientCookie("RAIL_EXPIRATION", "1512089431947"));
//        cookieStore.addCookie(new BasicClientCookie("RAIL_DEVICEID", "AIB-JdikDXrybYHGphEQMQ5STzSN_KNbfHvdQz07GTkD9skLr_oe51i0whmZMBxsEncyklWlG2TEYb77F13JJ-6O730sHhWw8qkHsCZAA8YUkkzbALBUSvbYhN-uMjpP20J5t8JSmmMIywyCjHmYE9iKNBn8CpLV"));
//        cookieStore.addCookie(new BasicClientCookie("JSESSIONID", "7E31ABE5DB895A9805C96D9E9F7CD791"));
//        cookieStore.addCookie(new BasicClientCookie("BIGipServerpool_passport", "317522442.50215.0000"));
//        cookieStore.addCookie(new BasicClientCookie("BIGipServerotn", "116392458.24610.0000"));
//
//        List<NameValuePair> valuePairList = new ArrayList<>();
//        valuePairList.add(new BasicNameValuePair("tk", "36whG9VfKlFUd3otJuZA5ETZAchz30SmbzDxGA45a2a0"));
//        valuePairList.add(new BasicNameValuePair("_json_att", ""));
//        HTTPBuilder builder = new HTTPBuilder().url(url).headers(headers).nameValuePairList(valuePairList).cookieStore(cookieStore);
//        System.out.println(HTTPClient.post(builder.build()));

//        HTTPBuilder builder = new HTTPBuilder();
//        String content = "测试代理网络";
//        JSONObject param = new JSONObject();
//        JSONObject mark = new JSONObject();
//        mark.put("content", content);
//        param.put("msgtype", "markdown");
//        param.put("markdown", mark);
//        HttpProxy proxy = new HttpProxy();
//        proxy.setHost("proxy-nonprod.svc.wecash.net");
//        proxy.setPort(8888);
//        builder.url("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=fba3dd08-c8ca-4939-897d-2fe036a6660d")
//                .param(param.toJSONString()).httpProxy(proxy);
//        HTTPClient.post(builder);
    }

    private static String getRndIP() {
        return String.format("%d.%d.%d.%d",
                RandomUtils.nextInt(1, 255),
                RandomUtils.nextInt(1, 255),
                RandomUtils.nextInt(1, 255),
                RandomUtils.nextInt(1, 255));
    }
}
